class_name BulletDevilSpear
extends RigidBody2D

@onready var collision_shape_2d: CollisionShape2D = $HitArea/CollisionShape2D
@onready var hit_area: Area2D = $HitArea
var hit_targets: Array = []
var sender: Node2D = null

@export var max_life: float = 5.0

var attack: float = 0
var critical_rate: float = 0
var critical_bonus: float = 0
var knockback: float = 0
var is_enemy: bool = true
var steal_hp_rate: float = 0
var level: Level = null
var hit_cam_shake_intensity: float = 0
var hit_cam_shake_duration: float = 0

@onready var shoot_sfx: AudioStreamPlayer2D = $AudioStreamPlayer2D


func _ready() -> void:
	shoot_sfx.play()
	
	await get_tree().create_timer(max_life).timeout
	queue_free()
	

func set_start_velocity(velocity: Vector2):
	linear_velocity = velocity


func _physics_process(delta: float) -> void:
	process_rotation(delta)
	process_hit()


func process_rotation(delta):
	if freeze: return
	
	if linear_velocity.length() > 0.1:
		rotation = linear_velocity.angle()


func process_hit():
	if collision_shape_2d.disabled: return
	
	var areas = hit_area.get_overlapping_areas()
	if areas.size() <= 0:
		return
		
	for area in areas:
		var source = area.source as Node2D
			
		if source not in hit_targets and source.has_method("take_hit"):
			hit_targets.append(source)
			var hit_data = get_hit_data()
			source.take_hit(hit_data, sender)
			
			level.camera.start_shake(hit_cam_shake_intensity, hit_cam_shake_duration)
			
			if source is UnitBase:
				stick_to_target(source)
				#add_poison_buff_to_target(source)
				steal_hp(hit_data, source)
				return
				
			queue_free()
			

func steal_hp(hit_data: HitData, source: Node2D):
	var actual_damage = hit_data.actual_damage
	var steal_hp = actual_damage * steal_hp_rate
	
	var hit_unit = source as UnitBase
	var level = get_tree().current_scene as Level
	var particle = level.emit_particle("particle_heal_hp_effect", hit_unit.ray_cast_point.global_position)
	
	particle.target = sender
	particle.heal_point = steal_hp
	
			
func get_hit_data():
	var is_critical = randf() <= critical_rate
	var critical_attack = attack * (1.0 + critical_bonus)
	
	var hit_data = HitData.new()
	hit_data.is_critical = is_critical
	hit_data.attack = critical_attack if is_critical else attack
	hit_data.knockback = knockback
	
	return hit_data
	

func _on_hit_area_body_entered(body: Node2D) -> void:
	collision_shape_2d.disabled = true
	
	linear_velocity = Vector2.ZERO
	angular_velocity = 0
	freeze = true
	freeze_mode = RigidBody2D.FREEZE_MODE_KINEMATIC
	
	level.camera.start_shake(hit_cam_shake_intensity, hit_cam_shake_duration)


func stick_to_target(target: Node2D) -> void:
	collision_shape_2d.disabled = true
	
	# 停止物理
	linear_velocity = Vector2.ZERO
	angular_velocity = 0
	freeze = true
	freeze_mode = RigidBody2D.FREEZE_MODE_KINEMATIC
	
	# 先保存当前全局位置与角度
	var pos = global_position
	var rot = global_rotation
	
	# 重新设置父节点
	get_parent().remove_child(self)
	var target_unit = target as UnitBase
	target_unit.stick_parent.add_child(self)
	
	# 保持位置和朝向不变（因为 reparent 会改变本地坐标系）
	global_position = pos
	global_rotation = rot
	

func set_is_enemy(b: bool):
	is_enemy = b
	if b:
		hit_area.set_collision_mask_value(7, true)
		hit_area.set_collision_mask_value(6, false)
	else:
		hit_area.set_collision_mask_value(7, false)
		hit_area.set_collision_mask_value(6, true)
	
	
	
